#include <plc2llvm/Visitor/strategy/pou_decl/VisitProg_Decl.h>
#include <plc2llvm/PLCSymbols/PLCProgramDeclSymbol.h>
#include <plc2llvm/PLCScopeStack.h>

VisitProg_Decl *VisitProg_Decl::VisitProg_Decl_Strategy = new VisitProg_Decl();

VisitProg_Decl::VisitProg_Decl() {
    registerMe(plcst::PLCSTParser::RuleProg_Decl);
}

std::any VisitProg_Decl::invoke(antlr4::ParserRuleContext *parserCtx, Visitor *visitor) {

    auto *ctx = dynamic_cast<plcst::PLCSTParser::Prog_DeclContext *>(parserCtx);
    //创建新的符号 & 创建新的作用域
    auto *programDeclSymbol = new PLCProgramDeclSymbol();
    auto* programScope = new PLCScope(programDeclSymbol);
    //获取符号名称
    auto name =ctx->prog_Type_Name()->getText();
    programDeclSymbol->setName(name);
    auto* parentScope = PLCScopeStack::getTopScope();
    //将符号添加到顶层作用域的符号表
    parentScope->addLocalSymbol(programDeclSymbol);
    //添加新的作用域到作用域栈
    PLCScopeStack::push(programScope);
    //访问变量声明段，变量的加表过程放在访问过程中，故忽略返回值
    //访问第3个到倒数第三个
    auto& childrenVector = ctx->children;
    for(int i = 2; i <= childrenVector.size() - 2; i++){
        visitor->visit(childrenVector[i]);
    }

    //访问fb_body
    visitor->visit(ctx->fB_Body());
    //访问结束，作用域出栈
    PLCScopeStack::pop();
    std::cout << "exit from program visit" << std::endl;
    return programDeclSymbol;
}
